package org.sninwo.lnbook.book.web.shiro;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sninwo.lnbook.uitls.LnBookUtils;

/**
 * 身份认证过滤器
 * @author LinZongxue
 *
 */
public class ShiroAuthcFilter extends FormAuthenticationFilter {
	private static Logger logger = LoggerFactory.getLogger(ShiroAuthcFilter.class);	

	/**
	 * 登陆成功后的处理
	 * @return true 允许继续访问登陆链接， false 禁止继续访问登陆链接
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
            ServletRequest request, ServletResponse response) throws Exception {
		
		//跳转到登陆成功后的页面(由于使用了ajax的方式，不需要跳转页面)
		//issueSuccessRedirect(request, response);
		
		logger.info("用户{}登陆成功", token.getPrincipal());
		
		return true;
	}
	
	/**
	 * 登陆失败后的处理
	 * @return true 允许继续访问登陆链接， false 禁止继续访问登陆链接
	 */
	@Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
            ServletRequest request, ServletResponse response) {
		setFailureAttribute(request, e);
		String msg = null;
		if (e instanceof UnknownAccountException){
			msg = "用户不存在";
		}
		else if (e instanceof IncorrectCredentialsException){
			msg = "密码错误";
		}
		else{
			msg = "未知原因";
		}
		request.setAttribute("loginError", msg); //保存失败信息，以供action类读取
		logger.info("用户{}登陆失败：{}", token.getPrincipal(), msg);
		
		return true;
	}
	
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws java.lang.Exception{
		HttpServletRequest req = (HttpServletRequest) request;
		//登陆链接，执行登陆
		if (isLoginRequest(request, response)){
			return super.onAccessDenied(request, response);
		}
		//登陆成功的链接，并不是因为登陆超时
		if (isSuccessRequest(req)){
			response.getWriter().print("{}");
		}
		//其它链接，当登陆超时处理
		else{
			logger.debug("访问被拒绝: {}", req.getRequestURI());
			Map<String, Object> r = new HashMap<String, Object>();
			r.put("loginTimeout", true);
			r.put("errorMsg", "登陆超时");
			response.getWriter().print(LnBookUtils.toJson(r));
		}
		return false;
	}
	
	private boolean isSuccessRequest(HttpServletRequest req){
		String successUrl = req.getContextPath() + getSuccessUrl();
		return successUrl.equals(req.getRequestURI());
	}
}
